Sample FLEX Macros


Available macros:


Opening a template file

Here's an easy way to open a file that you want to use as a template so you can put in information and save it under another name. In the example below, the template is a spreadsheet used for expense reports.

When you've typed in the macro, save it in ASCII format in your ~/.clarity/macros directory. Then, in Rapport, pull down the Options menu and choose Macros. Click on your new macro, give it a menu name and choose Menu Access. Now you can run it directly from the Rapport menu line.

(open-file "~/Admin/ExpRpts/Sample")
(setq answer (message-string "Name of file to be saved:" ))
(save-as answer)

Auto-scrolling through slides

Many of you have requested a capability for automatically scrolling through a slide show, without explicitly choosing "Next" from the Pop-Up menu or clicking on the page slider. Well, here's a macro that will do just that! It asks you how many seconds to pause between slides and how many times you want to go through the slide set, and then auto-scrolls acĀ” cording to your inputs.

;; ------------- ~/.clarity/macros/loop-slides-------------
;Ask how long to pause between slides
(setq sec (message-multiple-choice "Seconds between slides:" 
0 "2" "5" "8"
))

; Ask how many times to cycle through
(setq rep (message-multiple-choice "Number of repetitions:" 3 
"1" "5" "10" "25"))

(defun loop-slides-worker ()
   (choose-slide 1)
   (cond
       ((= sec 0)
            (system "sleep 2"))
       ((= sec 1)
            (system "sleep 5"))
       ((= sec 2)
            (system "sleep 8"))
    )
   (do
      ((result (next-slide) (next-slide))) ; bind & incr cond
      ((not (eq result T)) T) ; condition and return val
      (cond
         ((= sec 0)
            (system "sleep 2"))
         ((= sec 1)
            (system "sleep 5"))
         ((= sec 2)
            (system "sleep 8"))
      )
   )
)

(defun loop-slides (times)
   (dotimes (i times T)
      (loop-slides-worker)
   )

   ;; Go back to the first slide when done to reset properly
   (choose-slide 1)
)

(cond
       ((= rep 0)
            (loop-slides 1))
       ((= rep 1)
            (loop-slides 5))
       ((= rep 2)
            (loop-slides 10))
       ((= rep 3)
            (loop-slides 25))
    )

Data entry into spreadsheet

If you'd like to have your Rapport spreadsheet act as a data entry vehicle, here's a macro that reads the top row to determine column labels, then asks the user to supply data for each column in turn. It stops when the user presses Cancel or supplies a null value.

;;
;; find-maxcol returns a 1-based index to the first empty column
;; in row 1.
;;
(defun find-maxcol ()
   (do ((col 1) (continue 1))
      ((= continue 0)
       col)
      (table-select-cell 1 col)
      (if (= 0 (length (selected-text)))
	  (setq continue 0)
	  (setq col (+ 1 col))
      )
   )
)

;;
;; find-maxrow returns a 1-based index to the first empty row
;; in column 1.
;;
(defun find-maxrow ()
   (do ((row 1) (continue 1))
      ((= continue 0)
       row)
      (table-select-cell row 1)
      (if (= 0 (length (selected-text)))
	  (setq continue 0)
	  (setq row (+ 1 row))
      )
   )
)

;;
;; get-table-record asks via the message dialog for values
;; for each of the cells in the given row up to maxcol.
;;
;; It quits asking when a user enters an empty field, or when
;; the user hits Cancel.  Currently, there's a bug in the message
;; dialog that treats an empty field the same as Cancel; both states
;; return NIL.
;;
;; On latest Sun version of Rapport, hitting Cancel gives a NIL response,
;; as does returning an empty string.  Hitting Cancel or putting in an
;; empty string yields a response string of 0 length on other platforms.
;; So, we must check for both possibilities, and FIX THE BUG in the
;; code soon.
(defun empty-response (response)
   (or (equal response nil) (= (length response) 0))
)

(defun get-table-record (headers y maxcol)
   (do ((continue 1) (x 1) (heading "") (canceled nil))
      ((= continue 0) canceled)
      ;(table-select-cell 1 x)
      ;(setq heading (selected-text))
      (setq heading (car headers))
      (setq headers (cdr headers))
      ;; Set cell location before asking question
      ;; so user isn't confused as to where
      ;; the data is going
      (table-select-cell y x)
      (setq response
	 (message-string (strcat heading ":") ""))
      (if (empty-response response)
	 (progn
	    (setq continue 0)
	    (setq canceled t)
	 )
	 (progn
	    ;; Set the cell location again, in case the
	    ;; user accidentally moved the current cell
	    ;; while the dialog was up.
	    (table-select-cell y x)
	    (table-input response)
	    (setq x (+ 1 x))
	    (if (>= x maxcol)
	       (setq continue 0)
	       ()
	    ) ; end if we've looped to last column
	 )
      ) ; end if user hit cancel or gave empty response
   ) ; end loop
)


;;
;; get-multiple-records gets a record (row) of information
;;    at a time, asking for input via the message dialog.
;;    At the end of each row, the user is asked if he/she wants
;;    to continue with another record.  Hitting Cancel at this
;;    point stops the process.
;;
;; Hitting Cancel at any point while entering data stops the process.
;; Entering an empty string at any point also stops the process.
;; No default values are presented in the data entry message dialogs.
;;
(defun get-multiple-records (headers row maxcol)
   (do ((continue 1))
      ((= continue 0)	; end condition
	t)		; result of loop == return value
      (if (equal (get-table-record headers row maxcol) t)
	 (setq continue 0)
	 (if (empty-response (message-string "Continue or cancel?" "Continue"))
	    (setq continue 0)
	    (setq row (+ 1 row))
	 )
      )
   )
)

;;
;; get-headers: populates a list of headers such that
;;    you can map over the list using car(list) for the
;;    ith element, and cdr(list) is the list of remaining headers
;;
(defun get-headers (maxcol)
   (do ((continue 1) (x 1) (heading "") (hdrlist '()))
      ((= continue 0) hdrlist)
      (table-select-cell 1 (+ 1 (- maxcol x)))
      (setq heading (selected-text))
      (setq hdrlist (cons heading hdrlist))
      (if (>= x maxcol)
	 (setq continue 0)
	 (setq x (+ 1 x))
      )
   )
)

;;
;; This is the "main" program for this macro
;;
(let ((maxcol (find-maxcol))
      (maxrow (find-maxrow))
      (hdrlist '()))
   (setq hdrlist (get-headers maxcol))
   (get-multiple-records hdrlist maxrow maxcol)
)

Do you have Rapport macros you'd like to share with others? Or questions about how to use FLEX to satisfy a need you have? Let us know! Send an e-mail message or fax your macros or questions to Clarity at 415-964-4383.


Go to the Clarity Home page